package com.itheima.stock.service.impl;

import com.alibaba.excel.EasyExcel;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.gson.Gson;
import com.itheima.stock.common.StockInfoConfig;
import com.itheima.stock.common.domain.IncreaseQuery;
import com.itheima.stock.common.domain.InnerMarketDomain;
import com.itheima.stock.common.domain.StockExcelDomain;
import com.itheima.stock.mapper.StockBlockRtInfoMapper;
import com.itheima.stock.mapper.StockBusinessMapper;
import com.itheima.stock.mapper.StockMarketIndexInfoMapper;
import com.itheima.stock.mapper.StockRtInfoMapper;
import com.itheima.stock.pojo.StockBusiness;
import com.itheima.stock.service.StockService;
import com.itheima.stock.utils.DateTimeUtil;
import com.itheima.stock.vo.resp.PageResult;
import com.itheima.stock.vo.resp.R;
import com.itheima.stock.vo.resp.ResponseCode;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.locks.Condition;
import java.util.stream.Collectors;

//定义股票服务接口实现
@Service("stockService")
@Slf4j
public class StockServiceImpl implements StockService {

    @Autowired
    private StockBusinessMapper stockBusinessMapper;

    @Autowired
    private StockInfoConfig stockInfoConfig;
    //
    @Autowired
    private StockMarketIndexInfoMapper stockMarketIndexInfoMapper;

    @Autowired
    private StockRtInfoMapper stockRtInfoMapper;

    /**
     * 注入板块mapper
     */
    @Autowired
    private StockBlockRtInfoMapper stockBlockRtInfoMapper;


    @Override
    public R<List<StockBusiness>> findAllBusiness() {
        List<StockBusiness> list = stockBusinessMapper.findAll();
        return R.ok(list);
    }

    /**
     * 获取国内大盘的实时数据
     *
     * @return
     */
    @Override
    public R<List<InnerMarketDomain>> innerIndexAll() {
        //1.获取国内大盘的id集合
        List<String> innerIds = stockInfoConfig.getInner();
        //2.获取最近最新的股票有效交易日
        String lastDate = DateTimeUtil.getLastDateString4Stock(DateTime.now());
        lastDate = "20211226105600";//TODO 后续大盘数据实时拉去，将该行注释掉
        //3.调用mapper查询指定日期下对应的国内大盘数据
        List<InnerMarketDomain> maps = stockMarketIndexInfoMapper.selectByIdsAndDate(innerIds, lastDate);
        //组装响应的额数据
        if (CollectionUtils.isEmpty(maps)) {
            return R.error(ResponseCode.NO_RESPONSE_DATA.getMessage());
        }
        return R.ok(maps);
    }

    @Override
    public R<List<Map>> sectorAllLimit() {
        //1.调用mapper接口获取数据
        List<Map> infos = stockBlockRtInfoMapper.sectorAllLimit();
        //2.组装数据
        if (CollectionUtils.isEmpty(infos)) {
            return R.error(ResponseCode.NO_RESPONSE_DATA.getMessage());
        }
        return R.ok(infos);
    }

    /**
     * 涨幅榜
     * 沪深两市个股涨幅分时行情数据查询，以时间顺序查询前10条数据
     *
     * @return
     */
    @Override
    public R<List<IncreaseQuery>> stockIncreaseLimit() {
        //直接调用mapper查询前10的数据
        List<IncreaseQuery> infos = stockRtInfoMapper.stockIncreaseLimit();
        //判断是否有数据
        if (CollectionUtils.isEmpty(infos)) {
            return R.error(ResponseCode.NO_RESPONSE_DATA.getMessage());
        }
        return R.ok(infos);
    }

    /**
     * 沪深两市个股行情列表查询 ,以时间顺序和涨幅排序分页查询
     *
     * @param page     当前页
     * @param pageSize 每页大小
     * @return
     */
    @Override
    public R<PageResult<Map>> getStockAll(Integer page, Integer pageSize) {
        //设置分页查询
        PageHelper.startPage(page, pageSize);
        //通过mapper查询封装到PageResult下
        List<Map> infos = this.stockRtInfoMapper.getStockAll();
        //3.封装PageResult下
        //3.1封装PageInfo对象
        PageInfo<Map> listPageInfo = new PageInfo<Map>(infos);
        //3.2将PageInfo转PageResult
        PageResult<Map> pageResult = new PageResult<>(listPageInfo);
        //4.封装响应对象
        return R.ok(pageResult);
    }

    /**
     * 涨停跌停数
     * 沪深两市涨跌停分时行情数据查询，查询T日每分钟的涨跌停数据
     *
     * @return
     */
    @Override
    public R<Map> upDownCount() {
        //1.获取股票最近的有效交易日期,精确到秒
        String avlDate = DateTimeUtil.getLastDateString4Stock(DateTime.now());
        //TODO 后续数据实时获取时，注释掉
        avlDate = "20220106092500";
        //2.统计涨停的数据 约定：1代表涨停 0：跌停
        List<Map> upCount = stockRtInfoMapper.upDownCount(avlDate, 1);
        //3.统计跌停的数据
        List<Map> downCount = stockRtInfoMapper.upDownCount(avlDate, 0);
        //4.组装数据到map
        HashMap<String, List<Map>> info = new HashMap<>();
        info.put("upList", upCount);
        info.put("downList", downCount);
        //5.响应
        return R.ok(info);
    }

    @Override
    public void stockExport(HttpServletResponse response, Integer page, Integer pageSize) {
        try {
            //1.设置响应数据的类型:excel
            response.setContentType("application/vnd.ms-excel");
            //2.设置响应数据的编码格式
            response.setCharacterEncoding("utf-8");
            //3.设置默认的文件名称
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("stockRt", "UTF-8");
            //设置默认文件名称
            response.setHeader("content-disposition", "attachment;filename=" + fileName + ".xlsx");
            //4.分页查询股票数据
            PageHelper.startPage(page, pageSize);
            List<Map> infos = this.stockRtInfoMapper.getStockAll();
            Gson gson = new Gson();
            List<StockExcelDomain> excelDomains = infos.stream().map(map -> {
                StockExcelDomain domain = gson.fromJson(gson.toJsonTree(map), StockExcelDomain.class);
                return domain;
            }).collect(Collectors.toList());
            //5.导出
            EasyExcel.write(response.getOutputStream(), StockExcelDomain.class).sheet("股票数据").doWrite(excelDomains);
        } catch (IOException e) {
            log.info("股票excel数据导出异常，当前页：{}，每页大小：{}，异常信息：{}", page, pageSize, e.getMessage());
        }
    }


    /**
     * 成交量对比
     * 沪深两市个股涨跌行情数据查询，查询T日分时成交量与T-1日分时成交量对比数据
     * 简言之，统计两市成交量在每分钟的之和的统计；
     *
     * @return
     */
    @Override
    public R<Map> stockTradeVol4InnerMarket() {
        //1.获取最近的股票交易日时间，精确到秒 T交易日
        DateTime tDate = DateTimeUtil.getLastDate4Stock(DateTime.now());
        //转字符串
        String tStr = DateTimeUtil.parseToString4Stock(tDate);
        //TODO 后续注释掉
        tStr = "2022-01-03 14:30:00";
        //获取T-1交易日
        DateTime preTDate = DateTimeUtil.getPreviousTradingDay(tDate);
        //转字符串
        String preTStr = DateTimeUtil.parseToString4Stock(preTDate);
        //TODO 后续注释掉
        preTStr = "2022-01-02 14:30:00";
        //2.获取T日的股票大盘交易量统计数据
        List<Map> tData = stockMarketIndexInfoMapper.stockTradeVolCount(stockInfoConfig.getInner(), tStr);
        //3.获取T-1的数据
        List<Map> preTData = stockMarketIndexInfoMapper.stockTradeVolCount(stockInfoConfig.getInner(), preTStr);
        //4.组装数据
        HashMap<String, List<Map>> data = new HashMap<>();
        data.put("volList", tData);
        data.put("yesVolList", preTData);
        return R.ok(data);
    }

    /**
     * 查询指定时间下股票的涨跌幅度区间统计功能
     * 如果当前日期不在有效时间内，则以最近的一个股票交易时间作为查询时间点
     *
     * @param lastDateTime
     * @return
     */
    @Override
    public R<Map> stockUpDownScopeCount() {
        //获取当前时间下最近的一个股票交易时间
        String avlDate = DateTimeUtil.getLastDateString4Stock(DateTime.now());
        //TODO 后续删除
        avlDate = "20220106095500";
        //查询
        List<Map> maps = stockRtInfoMapper.stockUpDownScopeCount(avlDate);
        //获取去股票涨幅区间的集合
        List<String> upDownRange = stockInfoConfig.getUpDownRange();
//        //将list集合下的字符串映射成Map对象
//        List<Map> orderMap = upDownRange.stream().map(key->{
//            Optional<Map> title = maps.stream().filter(map -> key.equals(map.get("title"))).findFirst();
//            //判断对应的map是否存在
//            Map tmp =null;
//            if (title.isPresent()) {
//                tmp=title.get();
//            }else {
//                tmp = new HashMap();
//                tmp.put("title",key);
//                tmp.put("count",0);
//            }
//            return tmp;
//        }).collect(Collectors.toList());
        ArrayList<Map> orderMap = new ArrayList<>();
        for (String title : upDownRange) {
            Map tmp = null;
            for (Map map : maps) {
                if (title.equals(map.get("title"))) {
                    tmp = map;
                }
            }
            if (tmp == null) {
                tmp = new HashMap();
                tmp.put("title", title);
                tmp.put("count", 0);
            }
            orderMap.add(tmp);
        }

        //组装data
        HashMap<String, Object> data = new HashMap<>();
        data.put("time", avlDate);
        data.put("infos", maps);
        //返回响应
        return R.ok(data);
    }

    @Override
    public R<List<Map>> stockScreenTimeSharing(String code) {
        //1.获取最近有效的股票交易时间
        String avlDate = DateTimeUtil.getLastDateString4Stock(DateTime.now());
        //TODO 后续删除
        avlDate = "2021-12-30 09:32：54";
        List<Map> maps = stockRtInfoMapper.stockScreenTimeSharing(code, avlDate);
        //响应前端
        return R.ok(maps);
    }

    @Override
    public R<List<Map>> stockCreenDkLine(String code) {
        //获取当前日期前推20天
        Date forwardDate = DateTime.now().minusDays(20).toDate();
        //查询指定的股票在指定的日期范围内每天的股票统计数据
        List<Map> maps = stockRtInfoMapper.stockCreenDkLine(code, forwardDate);
        return R.ok(maps);
    }
}


